/*********************************************************************************
 *      Copyright:  (C) 2025 LingYun<<iot25@lingyun>>
 *                  All rights reserved.
 *
 *       Filename:  pack_data.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(25/05/25)
 *         Author:  LingYun <<iot25@lingyun>>
 *      ChangeLog:  1, Release initial version on "25/05/25 20:06:52"
 *                 
 ********************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdint.h>
  
#include "pack_data.h"
#include "logger.h"
  
// 定义 TLV 类型的枚举
typedef enum 
{
     TLV_TYPE_ID = 1,
     TLV_TYPE_TIME = 2,
     TLV_TYPE_TEMP = 3,
     TLV_TYPE_CRC = 4
} TlvType;

uint8_t crc8(const uint8_t *data, size_t length)
{
    uint8_t crc = 0;
    for (size_t i = 0; i < length; i++)
    {
        crc ^= data[i];
        for (int j = 0; j < 8; j++)
        {
            if (crc & 0x80)
            {
                crc = (crc << 1) ^ 0x07;
            }
            else
            {
                crc <<= 1;
            }
        }
    }
    return crc;
}

// pack_data 函数定义
int pack_data(packet_t *pack, char *data, int bytes)
{
    int          written = 0;
    uint8_t      crc;

    if ( NULL == pack || NULL == data || bytes <= 0 )
    {
        log_error("Invalid arguments: pack=%p, data=%p, bytes=%d", pack, data, bytes);
        return -1;
    }

    memset(data, 0, bytes);
    written=snprintf(data, bytes, "id:%s|time:%s|temp:%f", pack->dev_id, pack->dev_time, pack->dev_temp);

    if(written >= bytes)
    {
        printf("dev_id: %s, dev_time: %s, dev_temp: %f", pack->dev_id, pack->dev_time, pack->dev_temp);
        log_error("Buffer overflow: needed=%d, available=%d", written, bytes);
        return -2;
    }

    // 计算 CRC
   crc = crc8((const uint8_t *)data, written);
    if (written + 3 > bytes)
    { // 3 是 "|crc:" 和 CRC 十六进制表示的长度
        log_error("Buffer overflow when adding CRC: needed=%d, available=%d", written + 3, bytes);
        return -2;
    }

    written += snprintf(data + written, bytes - written, "|crc:0x%02X", crc);

    log_debug("pack_data successfully");
    return written;
}

// unpack_data 函数定义
int unpack_data(char *data, packet_t *pack)
{
    uint8_t      received_crc;
    size_t       data_length;

    if ( NULL == data || NULL == pack )
    {
        log_error("Invalid arguments: data=%p, pack=%p", data, pack);
        return -1;
    }

    memset(pack, 0, sizeof(packet_t));  // 正确初始化结构体

    sscanf(data, "id:%[^|]|time:%[^|]|temp:%f", pack->dev_id, pack->dev_time, &pack->dev_temp);

    // 计算 CRC
    data_length = strstr(data, "|crc:") - data;
    uint8_t calculated_crc = crc8((const uint8_t *)data, data_length);

    if (calculated_crc != received_crc)
    {
        log_error("CRC verification failed: calculated=0x%02X, received=0x%02X", calculated_crc, received_crc);
        return -1;
    }

    log_debug("unpack_data successful: id=%s, time=%s, temp=%.2f",pack->dev_id, pack->dev_time, pack->dev_temp);
    return 0;
}

// pack_tlv 函数定义
int pack_tlv(packet_t *pack, uint8_t *tlv_data, int bytes)
{
    int          offset = 0;
    uint8_t      id_type;
    uint8_t      id_length;
    uint8_t      time_type;
    uint8_t      time_length;
    uint8_t      temp_type;
    uint8_t      temp_length;
    uint8_t      crc;
    uint8_t      crc_type;
    uint8_t      crc_length;

    if (NULL == pack || NULL == tlv_data || bytes <= 0)
    {
        log_error("Invalid arguments: pack=%p, tlv_data=%p, bytes=%d", pack, tlv_data, bytes);
        return -1;
    }

    // 打包 ID
    id_type = TLV_TYPE_ID;
    id_length = strlen(pack->dev_id);

    if (offset + 2 + id_length > bytes)
    {
        log_error("Buffer overflow when packing ID TLV: needed=%d, available=%d", offset + 2 + id_length, bytes);
        return -2;
    }

    tlv_data[offset++] = id_type;
    tlv_data[offset++] = id_length;
    memcpy(tlv_data + offset, pack->dev_id, id_length);
    offset += id_length;

    // 打包时间
    time_type = TLV_TYPE_TIME;
    time_length = strlen(pack->dev_time);

    if (offset + 2 + time_length > bytes)
    {
        log_error("Buffer overflow when packing Time TLV: needed=%d, available=%d", offset + 2 + time_length, bytes);
        return -2;
    }
    tlv_data[offset++] = time_type;
    tlv_data[offset++] = time_length;
    memcpy(tlv_data + offset, pack->dev_time, time_length);
    offset += time_length;

    // 打包温度
    temp_type = TLV_TYPE_TEMP;
    temp_length = sizeof(float);
    if (offset + 2 + temp_length > bytes)
    {
        log_error("Buffer overflow when packing Temp TLV: needed=%d, available=%d", offset + 2 + temp_length, bytes);
        return -2;
    }

    tlv_data[offset++] = temp_type;
    tlv_data[offset++] = temp_length;
    memcpy(tlv_data + offset, &pack->dev_temp, temp_length);
    offset += temp_length;

    // 计算 CRC
    crc = crc8(tlv_data, offset);

    // 打包 CRC
    crc_type = TLV_TYPE_CRC;
    crc_length = sizeof(uint8_t);
    if (offset + 2 + crc_length > bytes)
    {
        log_error("Buffer overflow when packing CRC TLV: needed=%d, available=%d", offset + 2 + crc_length, bytes);
        return -2;
    }
    tlv_data[offset++] = crc_type;
    tlv_data[offset++] = crc_length;
    tlv_data[offset++] = crc;

    log_debug("pack_tlv successfully");
    return offset;
}

// unpack_tlv 函数定义
int unpack_tlv(uint8_t *tlv_data, int bytes, packet_t *pack)
{
    int          offset = 0;
    uint8_t      type;
    uint8_t      length;
    uint8_t      received_crc = 0;

    if (NULL == tlv_data || bytes <= 0 || NULL == pack)
    {
        log_error("Invalid arguments: tlv_data=%p, bytes=%d, pack=%p", tlv_data, bytes, pack);
        return -1;
    }

    while (offset < bytes)
    {
        type = tlv_data[offset++];
        length = tlv_data[offset++];

        switch (type)
        {
            case TLV_TYPE_ID: // ID
                if (length > sizeof(pack->dev_id) - 1)
                {
                    log_error("ID length exceeds buffer size");
                    return -1;
                }
                memcpy(pack->dev_id, tlv_data + offset, length);
                pack->dev_id[length] = '\0';
                break;

            case TLV_TYPE_TIME: // Time
                if (length > sizeof(pack->dev_time) - 1)
                {
                    log_error("Time length exceeds buffer size");
                    return -1;
                }
                memcpy(pack->dev_time, tlv_data + offset, length);
                pack->dev_time[length] = '\0';
                break;

            case TLV_TYPE_TEMP: // Temp
                if (length != sizeof(float))
                {
                    log_error("Invalid temperature length");
                    return -1;
                }
                memcpy(&pack->dev_temp, tlv_data + offset, length);
                break;

            case TLV_TYPE_CRC: // CRC
                if (length != sizeof(uint8_t))
                {
                    log_error("Invalid CRC length");
                    return -1;
                }
                received_crc = tlv_data[offset];
                break;

            default:
                log_error("Unknown TLV type: %d", type);
                return -1;
        }

        offset += length;
    }

    // 计算 CRC
    uint8_t calculated_crc = crc8(tlv_data, offset - 3); // 减去 CRC 的 TLV 长度

    if (calculated_crc != received_crc)
    {
        log_error("CRC verification failed: calculated=0x%02X, received=0x%02X", calculated_crc, received_crc);
        return -1;
    }

    log_debug("unpack_tlv successful: id=%s, time=%s, temp=%.2f", pack->dev_id, pack->dev_time, pack->dev_temp);
    return 0;
}

// pack_data_json 函数定义
int pack_data_json(packet_t *pack, char *data, int bytes)
{
    int          written = 0;

    if (NULL == pack || NULL == data || bytes <= 0)
    {
        log_error("Invalid arguments: pack=%p, data=%p, bytes=%d", pack, data, bytes);
        return -1;
    }

    memset(data, 0, bytes);
    written = snprintf(data, bytes, "{\"devid\":\"%s\", \"time\":\"%s\",\"temperature\":%.3f}",
                           pack->dev_id, pack->dev_time, pack->dev_temp);

    if (written >= bytes)
    {
        log_error("Buffer overflow: needed=%d, available=%d", written, bytes);
        return -2;
    }

    log_debug("pack_data_json successfully");
    return written;
}

